DispatcherServlet是怎么初始化各核心功能的? 您所在的位置:网站首页 timeval 初始化 DispatcherServlet是怎么初始化各核心功能的?

DispatcherServlet是怎么初始化各核心功能的?

2022-12-22 01:18| 来源: 网络整理| 查看: 265

之前的文章介绍了DispatcherServlet的各种核心功能,以及处理请求的流程。 今天要介绍的是,DispatcherServlet是怎么初始化各核心功能的? 换句话说,DispatcherServlet作为一个Servlet,它是在什么时候将MultipartResolver、HandlerMapping、HandlerAdapter以及HandlerExceptionResolver等添加为自己的成员变量的?

initStrategies()方法

首先,在DispatcherServlet中已经定义好了一个初始化方法:initStrategies()。 在该方法中会对各个功能模块进行初始化:

protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }

initStrategies()方法会将Spring上下文传递给各个子方法,方便各个子方法从容器中获取各自需要的bean对象。 在initXxx()方法中会对各自功能模块进行初始化。简单来说,就是从容器中获取对应的bean对象,设置为DispatcherServlet对应的成员变量。

这些initXxx()方法的初始化流程大同小异。

对于列表类型的成员变量(HandlerMapping、HandlerAdapter、HandlerExceptionResolver和ViewResolver),通过dectectAllXxx成员变量可以设置从容器中获取的是单个还是多个bean对象进行初始化:

true:根据类型(如HandlerMapping)从容器中获取多个bean对象,进行初始化。 false:根据名称(如handlerMapping)从容器中获取单个bean对象,进行初始化。

对于对象类型的成员变量(MultipartResolver、LocaleResolver、ThemeResolver、RequestToViewNameTranslator和FlashMapManager),它们只能根据名称(如multipartResolver)从容器中获取单个bean对象,进行初始化。

对于某些必须的功能模块(LocaleResolver、ThemeResolver、HandlerMapping、HandlerAdapter、HandlerExceptionResolver、RequestToViewNameTranslator、ViewResolver和FlashMapManager),如果从容器中获取不到对应的bean对象,会从DispatcherServlet.properties文件中加载默认的功能对象。

例如,initHandlerAdapters源码如下:

private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; if (this.detectAllHandlerAdapters) { // 1、从容器中加载所有类型为HandlerAdapter Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } else { try { // 2、从容器中加载名为handlerAdapter的HandlerAdapter HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { } } // 3、从DispatcherServlet.propeties中获取默认的HandlerAdapter this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerAdapters declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }

DispatcherServlet.properties中配置了默认的功能模块实现类,作为兜底。格式为功能模块全限定类名=功能模块实现类。例如:

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\ org.springframework.web.servlet.function.support.HandlerFunctionAdapter onRefresh()方法

DispatcherServlet中实现类FrameworkServlet的onRefresh()方法,会对所有功能模块进行初始化:

protected void onRefresh(ApplicationContext context) { initStrategies(context); }

onRefresh()方法会在容器刷新时调用。 在Spring Boot项目中,如果在onRefresh()中添加断点,会发现在项目启动时不会进入该断点,说明项目启动时并不会初始化DispatcherServlet的各个功能模块。 在第一次请求时,才会触发该方法。

原文地址:https://www.cnblogs.com/Xianhuii/p/16977083.html



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有